#include <iostream>
#include <mutex>

// 定制删除器shared_ptr
template <class T>
struct default_delete
{
    void operator()(T *ptr)
    {
        if (ptr)
        {
            delete ptr;
            ptr = nullptr;
        }
    }
};

template <class T, class Deleter = default_delete<T>>
class shared_ptr
{
public:
    shared_ptr(T *ptr = nullptr)
        : _ptr(ptr), _pcount(new int(1)), _mutex(new std::mutex)
    {
    }

    void Release()
    {
        bool flag = false;
        _mutex->lock();
        if (--(*_pcount) == 0)
        {
            flag = true;
            _deleter(_ptr);
            delete _pcount;
        }
        _mutex->unlock();
        if (flag)
        {
            delete _mutex;
        }
    }
    ~shared_ptr()
    {
        Release();
    }

    shared_ptr(const shared_ptr<T> &sp)
        : _ptr(sp._ptr), _pcount(sp._pcount), _mutex(sp._mutex)
    {
        _mutex->lock();
        (*_pcount)++;
        _mutex->unlock();
    }

    shared_ptr<T> &operator=(const shared_ptr<T> &sp)
    {
        if (&sp != this)
        {
            Release();

            _ptr = sp._ptr;
            _pcount = sp._pcount;
            _mutex = sp._mutex;

            _mutex->lock();
            (*_pcount)++;
            _mutex->unlock();
        }
        return *this;
    }

    T &operator*()
    {
        return *_ptr;
    }

    T *operator->()
    {
        return _ptr;
    }

    int use_count() const
    {
        std::unique_lock<std::mutex> lock(*_mutex);
        return *_pcount;
    }

private:
    T *_ptr;
    int *_pcount;
    std::mutex *_mutex;
    Deleter _deleter;
};

int main()
{
    int *p1 = new int(1);
    int *p2 = new int(2);
    shared_ptr<int> sp1(p1);
    shared_ptr<int> sp2(p2);
    shared_ptr<int> sp3(sp2);
    sp3 = sp1;

    std::cout << "sp1 use count: " << sp1.use_count() << std::endl;
    std::cout << "sp2 use count: " << sp2.use_count() << std::endl;
    std::cout << "sp3 use count: " << sp3.use_count() << std::endl;
    return 0;
}